# -*- coding: utf-8 -*-
# @Time    : 2024/7/17 11:03
# @Author  : yujiahao
# @File    : 35_fastapi_middleware.py
# @description:中间件


"""
中间件的使用：
---------------
1. 你可以向 FastAPI 应用添加中间件。
2. "中间件"是一个函数，它在每个请求被特定的路径操作处理之前，以及在每个响应返回之前工作。

中间件的工作流程：
---------------------
1. 它接收你的应用程序的每一个请求。
2. 然后它可以对这个请求做一些事情或者执行任何需要的代码。
3. 然后它将请求传递给应用程序的其他部分（通过某种路径操作）。
4. 然后它获取应用程序生产的响应（通过某种路径操作）。
5. 它可以对该响应做些什么或者执行任何需要的代码。
6. 然后它返回这个响应。
"""

import time

from fastapi import FastAPI, Request

app = FastAPI()

# 创建中间件

'''
要创建中间件可以在函数的顶部使用装饰器 @app.middleware("http").

中间件参数接收如下参数:

    - request.
    - 一个函数 call_next 它将接收 request 作为参数.
        - 这个函数将 request 传递给相应的 路径操作.
        - 然后它将返回由相应的路径操作生成的 response.
    - 然后你可以在返回 response 前进一步修改它.
'''


@app.middleware("http")
async def add_process_time_header(request: Request, call_next):
    start_time = time.time()
    # 处理请求并获取响应
    # call_next(request) 将请求传递给下一个中间件或最终的请求处理函数，并等待其完成。
    # 这个调用会返回一个响应对象 response。包括：
    # 响应状态码：如 200、404、500 等。
    # 响应头：所有的 HTTP 响应头信息。
    # 响应体：实际的响应内容（如 JSON 数据、HTML 页面等）
    response = await call_next(request)
    process_time = time.time() - start_time
    """
    自定义请求头：
    ---------------
    1. 请记住可以用 'X-' 前缀添加专有自定义请求头。
    2. 但是如果你想让浏览器中的客户端看到你的自定义请求头，你需要把它们加到 CORS 配置的 expose_headers 参数中。
    3. 详细信息请参阅 Starlette 的 CORS 文档（https://www.starlette.io/middleware/#corsmiddleware）。

    技术细节：
    -----------
    1. 你也可以使用 from starlette.requests import Request。
    2. FastAPI 为了开发者方便提供了该对象，但其实它直接来自于 Starlette。
    
    【在 response 的前和后】
    在任何路径操作收到request前,可以添加要和请求一起运行的代码.
    也可以在响应生成但是返回之前添加代码.
    例如你可以添加自定义请求头 X-Process-Time 包含以秒为单位的接收请求和生成响应的时间:
    """
    # 添加自定义响应头
    response.headers["X-Process-Time"] = str(process_time)
    print(response)
    return response
